﻿using Kinlo.MESDocking;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using UIWindows.GlobalStatics;
using UIWindows.Models.Devices;
using UIWindows.Models.ParameterModels;
using UIWindows.Views;
using XingLucifer.Devices;
using XingLucifer.IBase.Enums;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window;

namespace UIWindows.Services.PLC_MESHelper
{
    /// <summary>
    ///  检测触摸屏基础操作，登录、获取工单、执行工单等
    /// </summary>
    public class PLCBaseOperateHelper : HelperBase
    {

        PLCBase InjMachine { get; set; }

        ObservableCollection<MesOutputParameterModel> _mesParameter { get; set; }

        MESProcessParameter _mesProcessParameter { get; set; }

        MESUserNameCheck mesUserInteraction { get; set; }
        public PLCBaseOperateHelper(
              DeviceInteractiveaddressStatic deviceInteractiveaddressStatic,
            DeviceClientModel deviceModel,
            TemporaryStatic temporaryStatic,
            ParameterStatic parameterStatic,
            DeviceConfigStatic deviceConfigStatic,
            SystemConfigStatic systemConfigStatic,
             HomeStatic homeStatic,
             Action<string, string, string, string, string, long, DateTime, string, string, string, string> log, Action<string, string, string> dialog
            ) : base(deviceInteractiveaddressStatic, deviceModel, temporaryStatic, parameterStatic, deviceConfigStatic, systemConfigStatic, homeStatic, log, dialog)
        {
            InjMachine = deviceModel.PLC;
            mesUserInteraction = new MESUserNameCheck(_log, _dialog,machineInfo_Type);


            if (_deviceInteractiveaddressStatic.MesOutputParameters != null && _deviceInteractiveaddressStatic.MesOutputParameters.ContainsKey(machineInfo_Type))
            {
                _mesParameter = _deviceInteractiveaddressStatic.MesOutputParameters[machineInfo_Type];
            }


            _mesProcessParameter = new MESProcessParameter(_log, _dialog, machineInfo_Type);
        }

        //上次工单序号
        int last_workOrderStatus = -1;

        //是否已经获取工单
        bool isworkOrde = false;
        /// <summary>
        ///
        /// </summary>
        public override Task Handle()
        {
            try
            {
                if (_baseParamete==null|| _baseParamete.Count==0)
                {
                    return Task.CompletedTask;
                }

                #region 用户工号校验
                //获取用户工号校验请求状态
                if (_baseParamete.Any(x => x.Name.Contains("UserCheckAdress")))
                {
                    var addReassData = GetAddReassData("UserCheckAdress");
                    var userCheck = InjMachine.Read(addReassData.PLCAddress, 1);
                    if (userCheck != null && userCheck[0] == 1)
                    {
                        var testMMo = _deviceModel;
                        User_Elapsed();
                    }
                }
                #endregion


                #region 检测当前选中的工单序号有没有改变,改变则写入批次号、写入型号
                if (_baseParamete.Any(x => x.Name.Contains("WorkOrderNumAdress")))
                {
                    Write_lstPC_No_lstMaterial_Spec();
                }


                #endregion

                #region 获取工单
                if (_baseParamete.Any(x => x.Name.Contains("WorkOrderStatusAdress")))
                {
                    TaskWorkOrder();
                }
                #endregion


                #region 执行保存工单
                if (_baseParamete.Any(x => x.Name.Contains("WorkOrderSaveStatusAdress")))
                {
                    TaskWorkOrderSave();
                }

                #endregion


            }
            catch (Exception ex)
            {
                RunLog($" 基础触摸屏交互，登录，获取工单、等异常{ex}");
            }
   
            return Task.CompletedTask;

        }

        /// <summary>
        /// 用户工号校验
        /// </summary>
        private void User_Elapsed()
        {

            try
            {
                var addressData = GetAddReassData("UserNameAddress");


                //获取用户工号
                var username = InjMachine.ReadString(addressData.PLCAddress, 10);

                addressData = GetAddReassData("ClassAddress");
                //获取班组
                var classValue = InjMachine.Read(addressData.PLCAddress, 1);

                addressData = GetAddReassData("ClassTeamAddress");
                //获取班次
                var ClassTeamValue = InjMachine.Read(addressData.PLCAddress, 1);

                addressData = GetAddReassData("EquipmentCodeAddress");
                // 获取设备编码
                var EquipmentCode = InjMachine.ReadString(addressData.PLCAddress, 8);

                addressData = GetAddReassData("process_idAddress");
                // 获取工序编码
                var process_id = InjMachine.ReadString(addressData.PLCAddress, 8);

                addressData = GetAddReassData("UserCheckResultAdress");



                Dictionary<string, object> mesParam = new Dictionary<string, object>
                    {
                        { "EquipmentCode", _parameter.EquipmentCode==null?"": _parameter.EquipmentCode },
                        { "process_id", _parameter.process_id==null?"": _parameter.process_id },
                    };

                var mesParameters = new Dictionary<string, object>()
                {
                    {"WorkNumber",username }
                };

                mesParam.Add("parameter", mesParameters);
                var re = mesUserInteraction.MESInteraction(_parameterStatic.MESParameter.AccountRoute,
                     _parameterStatic.MESParameter.AccountTime,
                     1, DateTime.Now, mesParam);

                if (re == ResultTypes.合格)
                {
                    //工号校验成功

                    //更换工号或者更换班组班次
                    if (_parameter.UserName != username || _parameter.Class != classValue[0].ToString() || _parameter.ClassTeam != ClassTeamValue[0].ToString())
                    {
                        //更换工号调用生产统计接口
                        //MESCountUpLoad();
                        if(!string.IsNullOrWhiteSpace(_parameter.UserName))
                        {
                            MESCountUpLoad_Hour($"更换工号{_parameter.UserName}=>{username}");

                            try
                            {
                                Upload_Parameters(_mesParameter, _mesProcessParameter);
                            }
                            catch (Exception ex)
                            {
                                RunLog($"更换工号{_parameter.UserName}=>{username} 调用工艺参数接口异常:{ex.ToString()}");
                            }

                        }
                       
                    }

                    //保存到文件
                    _parameter.Class = classValue[0].ToString();
                    _parameter.ClassTeam = ClassTeamValue[0].ToString();
                    _parameter.HasValidEmployeeId = 1;
                    _parameter.HasValidUserName = username;
                    _parameter.UserName = username;
                    _parameter.EquipmentCode = EquipmentCode;
                    _parameter.process_id = process_id;


                    //写入PLC成功信号
                    InjMachine.Write(addressData.PLCAddress, new short[] { 2 });
                }
                else
                {
                    //工单校验失败
                    _parameter.HasValidEmployeeId = 2;
                    _parameter.HasValidUserName = null;
                    //保存到文件
                    InjMachine.Write(addressData.PLCAddress, new short[] { 4 });
                }
            }
            catch (Exception ex)
            {
                RunLog($"【用户校验定时任务异常】:{ex.ToString()}");
            }
        }

        /// <summary>
        ///  检测当前选中的工单序号有没有改变,改变则写入批次号、写入型号
        /// </summary>
        private void Write_lstPC_No_lstMaterial_Spec()
        {
            try
            {
                var addReassData = GetAddReassData("WorkOrderNumAdress");
                var workOrderNum = InjMachine.Read(addReassData.PLCAddress, 1);

                //检测当前选中的工单序号有没有改变
                if (workOrderNum != null && workOrderNum[0] != last_workOrderStatus && isworkOrde)
                {
                    var addressData = GetAddReassData("PC_NoAddress");
                    //清空批次号地址
                    InjMachine.ClearPLCAddress(addressData.PLCAddress, 10);

                    //写入批次号
                    InjMachine.WriteStringAsUInt16(addressData.PLCAddress, _parameter.lstPC_No[workOrderNum[0]]);

                    addressData = GetAddReassData("Material_SpecAddress");
                    //清空型号地址
                    InjMachine.ClearPLCAddress(addressData.PLCAddress, 10);
                    //写入型号
                    InjMachine.WriteStringAsUInt16(addressData.PLCAddress, _parameter.lstMaterial_Spec[workOrderNum[0]]);
                }
            }
            catch (Exception ex)
            {
                RunLog($"【写入批次号型号异常】:{ex.ToString()}");
            }



        }

        /// <summary>
        /// 获取工单
        /// </summary>
        private async void TaskWorkOrder()
        {
            try
            {
                var addReassData = GetAddReassData("WorkOrderStatusAdress");
                //工单获取请求状态
                var workOrderStatus = InjMachine.Read(addReassData.PLCAddress, 1);
                //List<int> workOrderStatus = new List<int> { 4 };
                if (workOrderStatus != null && workOrderStatus[0] == 1)
                {

                    //工单号
                    var lstBill_No = new List<string>();
                    //料号
                    var lstMaterial_Code = new List<string>();
                    //型号
                    var lstMaterial_Spec = new List<string>();
                    //订单批号
                    var lstPC_No = new List<string>();
                    //工单状态
                    var lstWorkOrderStatus_Name = new List<string>();
                    //计划开始时间
                    var lstPlanedStart = new List<string>();
                    //计划结束时间
                    var lstPlanedEndDate = new List<string>();
                    //订单号
                    var lstProductionOrderNO = new List<string>();

                    //// 获取设备编码
                    //var EquipmentCode = InjMachine.PLC.ReadString(_data.EquipmentCodeAddress, 10);
                    ////var EquipmentCode =_data.EquipmentCode;
                    //// 获取工序编码
                    //var process_id = InjMachine.PLC.ReadString(_data.process_idAddress, 10);


                    // 获取设备编码
                    var EquipmentCode = _parameter.EquipmentCode;
                    //var EquipmentCode =_data.EquipmentCode;
                    // 获取工序编码
                    var process_id = _parameter.process_id;


                    var interaction = new GetByProductCodeInterface(_log, _dialog,machineInfo_Type);


                    Dictionary<string, object> mesParam = new Dictionary<string, object>
                    {
                       {"equipment_id",EquipmentCode },
                        {"process_id",process_id }
                    };


                    var result =await interaction.MESInteractionAsync(_parameterStatic.MESParameter.GetByProductCodeRoute,
                         _parameterStatic.MESParameter.GetByProductCodeTime,
                         1, DateTime.Now, mesParam);



                    if (result == ResultTypes.合格)
                    {
                        addReassData = GetAddReassData("WorkOrderCountAddress");
                        object resultValue = mesParam["result"];

                        // 检查值的类型是否是 List<Dictionary<string, object>>
                        if (resultValue is List<Dictionary<string, object>> resultList)
                        {
                            // 现在你可以使用 resultList，比如获取长度
                            int resultListLength = resultList.Count;

                            InjMachine.Write(addReassData.PLCAddress, new short[] { (short)resultListLength });


                            for (int i = 0, j = 0; i < resultListLength; i++)
                            {
                                //Workorders.Add(new ComboxItem { Name = result[i].Bill_No, Value = result[i].Bill_No });
                                lstBill_No.Add(resultList[i]["Bill_No"]?.ToString() ?? "");
                                lstMaterial_Code.Add(resultList[i]["Material_Code"]?.ToString() ?? "");
                                lstMaterial_Spec.Add(resultList[i]["Material_Spec"]?.ToString() ?? "");
                                lstPC_No.Add(resultList[i]["PC_No"]?.ToString() ?? "");
                                lstWorkOrderStatus_Name.Add(resultList[i]["WorkOrderStatus_Name"]?.ToString() ?? "");
                                lstPlanedStart.Add(resultList[i]["PlanedStart"]?.ToString() ?? "");
                                lstPlanedEndDate.Add(resultList[i]["PlanedEndDate"]?.ToString() ?? "");
                                lstProductionOrderNO.Add(resultList[i]["ProductionOrderNO"]?.ToString() ?? "");

                                addReassData = GetAddReassData("lstWorkOrderListAddress");
                                // 从地址中 中提取数字部分
                                string numericPart = new string(addReassData.PLCAddress.Where(char.IsDigit).ToArray());

                                // 将数字部分转换成整数，并与 j 相加
                                int sum = int.Parse(numericPart) + j;

                                // 将新的数字部分和原来的字母部分组合成新的字符串
                                string resultAddress = addReassData.PLCAddress.Replace(numericPart, sum.ToString());
                                //将工单写入plc
                                InjMachine.WriteStringAsUInt16(resultAddress, resultList[i]["Bill_No"].ToString());
                                //写完一个工单地址加十，写下一个工单
                                j += 10;
                            }
                            //WorkorderSelectedValue = result[0].Bill_No;
                            //WorkorderSelectedValue = Data.MachineList[index].WorkOrder;
                            //DoCmdOrderSelectionChanged();
                            _parameter.lstBill_No = lstBill_No;
                            _parameter.lstMaterial_Code = lstMaterial_Code;
                            _parameter.lstMaterial_Spec = lstMaterial_Spec;
                            _parameter.lstPC_No = lstPC_No;
                            _parameter.lstWorkOrderStatus_Name = lstWorkOrderStatus_Name;
                            _parameter.lstPlanedStart = lstPlanedStart;
                            _parameter.lstPlanedEndDate = lstPlanedEndDate;
                            _parameter.lstProductionOrderNO = lstProductionOrderNO;

                            addReassData = GetAddReassData("WorkOrderWriteResultAdress");
                            //写入工单成功信号给plc刷新
                            InjMachine.Write(addReassData.PLCAddress, new short[] { 1 });

                            addReassData = GetAddReassData("WorkOrderResultAdress");
                            //写入工单获取结果信息
                            InjMachine.Write(addReassData.PLCAddress, new short[] { 2 });

                            if (_parameter.lstPC_No!=null && _parameter.lstPC_No.Count>0
                                && _parameter.lstMaterial_Spec != null && _parameter.lstMaterial_Spec.Count > 0)
                            {
                                var addressData = GetAddReassData("PC_NoAddress");
                                //清空批次号地址
                                InjMachine.ClearPLCAddress(addressData.PLCAddress, 10);
                                //写入批次号
                                InjMachine.WriteStringAsUInt16(addressData.PLCAddress, _parameter.lstPC_No[0]);

                                addressData = GetAddReassData("Material_SpecAddress");
                                //清空型号地址
                                InjMachine.ClearPLCAddress(addressData.PLCAddress, 10);
                                //写入型号
                                InjMachine.WriteStringAsUInt16(addressData.PLCAddress, _parameter.lstMaterial_Spec[0]);
                            }
                           

                            isworkOrde = true;

                            RunLog($"工单获取成功");
                        }
                        else
                        {
                            RunLog($"工单数据转换List字典失败：{resultValue}");
                        }
                    }
                    else
                    {
                        addReassData = GetAddReassData("WorkOrderResultAdress");
                        InjMachine.Write(addReassData.PLCAddress, new short[] { 3 });
                        //MessageBox.Show($"工单获取失败!");
                        RunLog($"工单获取失败!");
                    }
                }
            }
            catch (Exception ex)
            {
                RunLog($"【触摸屏获取工单异常】:{ex.ToString()}");
            }


        }



        //获取工单测试
        public async Task TaskWorkOrderTest()
        {
            //工单号
            var lstBill_No = new List<string>();
            //料号
            var lstMaterial_Code = new List<string>();
            //型号
            var lstMaterial_Spec = new List<string>();
            //订单批号
            var lstPC_No = new List<string>();
            //工单状态
            var lstWorkOrderStatus_Name = new List<string>();
            //计划开始时间
            var lstPlanedStart = new List<string>();
            //计划结束时间
            var lstPlanedEndDate = new List<string>();
            //订单号
            var lstProductionOrderNO = new List<string>();

            //// 获取设备编码
            //var EquipmentCode = InjMachine.PLC.ReadString(_data.EquipmentCodeAddress, 10);
            ////var EquipmentCode =_data.EquipmentCode;
            //// 获取工序编码
            //var process_id = InjMachine.PLC.ReadString(_data.process_idAddress, 10);


            // 获取设备编码
            var EquipmentCode = _parameter.EquipmentCode;
            //var EquipmentCode =_data.EquipmentCode;
            // 获取工序编码
            var process_id = _parameter.process_id;


            var interaction = new GetByProductCodeInterface(_log, _dialog, machineInfo_Type);

            Dictionary<string, object> mesParam = new Dictionary<string, object>
                    {
                        { "EquipmentCode", _parameter.EquipmentCode==null?"": _parameter.EquipmentCode },
                        { "process_id", _parameter.process_id==null?"": _parameter.process_id },
                    };
            var result = await interaction.MESInteractionAsync(_parameterStatic.MESParameter.GetByProductCodeRoute,
                         _parameterStatic.MESParameter.GetByProductCodeTime,
                 1, DateTime.Now, mesParam);



            if (result == ResultTypes.合格)
            {
                //addReassData = GetAddReassData("WorkOrderCountAddress");
                object resultValue = mesParam["result"];

                // 检查值的类型是否是 List<Dictionary<string, object>>
                if (resultValue is List<Dictionary<string, object>> resultList)
                {
                    // 现在你可以使用 resultList，比如获取长度
                    int resultListLength = resultList.Count;

                    //InjMachine.Write(addReassData.PLCAddress, new short[] { (short)resultListLength });


                    for (int i = 0, j = 0; i < resultListLength; i++)
                    {
                        //Workorders.Add(new ComboxItem { Name = result[i].Bill_No, Value = result[i].Bill_No });
                        lstBill_No.Add(resultList[i]["Bill_No"]?.ToString() ?? string.Empty);
                        lstMaterial_Code.Add(resultList[i]["Material_Code"]?.ToString() ?? string.Empty);
                        lstMaterial_Spec.Add(resultList[i]["Material_Spec"]?.ToString() ?? string.Empty);
                        lstPC_No.Add(resultList[i]["PC_No"]?.ToString() ?? string.Empty);
                        lstWorkOrderStatus_Name.Add(resultList[i]["WorkOrderStatus_Name"]?.ToString() ?? string.Empty);
                        lstPlanedStart.Add(resultList[i]["PlanedStart"]?.ToString() ?? string.Empty);
                        lstPlanedEndDate.Add(resultList[i]["PlanedEndDate"]?.ToString() ?? string.Empty);
                        lstProductionOrderNO.Add(resultList[i]["ProductionOrderNO"]?.ToString() ?? string.Empty);

                        var addressData = GetAddReassData("lstWorkOrderListAddress");

                        // 从地址中 中提取数字部分
                        string numericPart = new string(addressData.PLCAddress.Where(char.IsDigit).ToArray());

                        // 将数字部分转换成整数，并与 j 相加
                        int sum = int.Parse(numericPart) + j;

                        addressData = GetAddReassData("lstWorkOrderListAddress");

                        // 将新的数字部分和原来的字母部分组合成新的字符串
                        string resultAddress = addressData.PLCAddress.Replace(numericPart, sum.ToString());
                        //将工单写入plc
                        //InjMachine.WriteStringAsUInt16(resultAddress, resultList[i]["Bill_No"].ToString());
                        //写完一个工单地址加十，写下一个工单
                        j += 10;
                    }
                    //WorkorderSelectedValue = result[0].Bill_No;
                    //WorkorderSelectedValue = Data.MachineList[index].WorkOrder;
                    //DoCmdOrderSelectionChanged();
                    _parameter.lstBill_No = lstBill_No;
                    _parameter.lstMaterial_Code = lstMaterial_Code;
                    _parameter.lstMaterial_Spec = lstMaterial_Spec;
                    _parameter.lstPC_No = lstPC_No;
                    _parameter.lstWorkOrderStatus_Name = lstWorkOrderStatus_Name;
                    _parameter.lstPlanedStart = lstPlanedStart;
                    _parameter.lstPlanedEndDate = lstPlanedEndDate;
                    _parameter.lstProductionOrderNO = lstProductionOrderNO;

                    //addReassData = GetAddReassData("WorkOrderWriteResultAdress");
                    ////写入工单成功信号给plc刷新
                    //InjMachine.Write(addReassData.PLCAddress, new short[] { 1 });

                    //addReassData = GetAddReassData("WorkOrderResultAdress");
                    ////写入工单获取结果信息
                    //InjMachine.Write(addReassData.PLCAddress, new short[] { 2 });

                    isworkOrde = true;
                }
                else
                {
                    RunLog($"工单数据转换List字典失败：{resultValue}");
                }
            }
            else
            {
                //addReassData = GetAddReassData("WorkOrderResultAdress");
                //InjMachine.Write(addReassData.PLCAddress, new short[] { 3 });
                //MessageBox.Show($"工单获取失败!");
                RunLog($"工单获取失败!");
            }


        }
        /// <summary>
        /// 执行保存工单
        /// </summary>
        private void TaskWorkOrderSave()
        {
            try
            {
                var addReassData = GetAddReassData("WorkOrderSaveStatusAdress");

                //工单保存请求状态
                var workOrderSaveStatus = InjMachine.Read(addReassData.PLCAddress, 1);
                if (workOrderSaveStatus != null && workOrderSaveStatus[0] == 1)
                {
                    addReassData = GetAddReassData("WorkOrderAddress");
                    // 获取工单号
                    var workOrder = InjMachine.ReadString(addReassData.PLCAddress, 10);

                    if (_parameter.lstBill_No!=null&&_parameter.lstBill_No.Any(item => item == workOrder))
                    {

                        //获取工单在第几个序号
                        int number = _parameter.lstBill_No.FindIndex(item => item == workOrder);

                        //保存未切换的工单
                        var lastWorkOrder = _parameter.WorkOrder;

                        //切换工单则用切换前的工单调用生产统计接口
                        if (lastWorkOrder != _parameter.lstBill_No[number])
                        {
                            //MESCountUpLoad();
                            if (!string.IsNullOrWhiteSpace(lastWorkOrder))
                            {
                                MESCountUpLoad_Hour($"更换工单{lastWorkOrder}=>{_parameter.lstBill_No[number]}");

                                try
                                {
                                    Upload_Parameters(_mesParameter, _mesProcessParameter);
                                }
                                catch (Exception ex)
                                {
                                    RunLog($"更换工单{lastWorkOrder}=>{_parameter.lstBill_No[number]} 调用工艺参数接口异常:{ex.ToString()}");
                                }
                            }
                        }

                        _parameter.WorkOrder = _parameter.lstBill_No[number];
                        _parameter.Material_Code = _parameter.lstMaterial_Code[number];
                        _parameter.Material_Spec = _parameter.lstMaterial_Spec[number];
                        _parameter.BatchNo = _parameter.lstPC_No[number];
                        _parameter.WorkOrderStatus_Name = _parameter.lstWorkOrderStatus_Name[number];
                        _parameter.PlanedStart = _parameter.lstPlanedStart[number];
                        _parameter.PlanedEndDate = _parameter.lstPlanedEndDate[number];
                        _parameter.ProductionOrderNO = _parameter.lstProductionOrderNO[number];

                        //切换工单则用新工单调用标准参数接口
                        if (lastWorkOrder != _parameter.lstBill_No[number])
                        {
                            PumDataSave();

                         

                        }
                        addReassData = GetAddReassData("WorkOrderSaveStatusAdress");
                        //写入PLC成功信号
                        InjMachine.Write(addReassData.PLCAddress, new short[] { 0 });
                    }
                    else
                    {
                        addReassData = GetAddReassData("WorkOrderResultAdress");
                        //执行保存工单失败
                        InjMachine.Write(addReassData.PLCAddress, new short[] { 4 });
                        //InjMachine.PLC.Write(_data.WorkOrderAddress, new short[] { 2});
                    }
                }
            }catch (Exception ex)
            {
                RunLog($"执行保存工单异常{ex}");
            }
           
        }


    }
}
